Accidentes automovilisticos Conjunto de datos EDA

En este apartado vamos a analizar datos de accidentes automovilisticos
Python
Autor/a

Joel burbano

Fecha de publicación

13 de enero de 2024

Importamos las librerias necesarias

Código
import numpy as np
import seaborn as sb
import matplotlib.pyplot as plt
import pandas as pd

pd.options.display.max_columns=None #para que se despliegue todas las columnas

import warnings 
warnings.filterwarnings('ignore')
from matplotlib import cm
c4=cm.get_cmap('Set3')

Cargamos la data

Código
df=pd.read_excel("dataset.xlsx")

Revisemos las 5 primeras filas de datos

Código
df.head(5)
Year Month Day Weekend? Hour Collision Type Injury Type Primary Factor Reported_Location Latitude Longitude
0 2015 1 5 Weekday 0.0 2-Car No injury/unknown OTHER (DRIVER) - EXPLAIN IN NARRATIVE 1ST & FESS 39.159207 -86.525874
1 2015 1 6 Weekday 1500.0 2-Car No injury/unknown FOLLOWING TOO CLOSELY 2ND & COLLEGE 39.161440 -86.534848
2 2015 1 6 Weekend 2300.0 2-Car Non-incapacitating DISREGARD SIGNAL/REG SIGN BASSWOOD & BLOOMFIELD 39.149780 -86.568890
3 2015 1 7 Weekend 900.0 2-Car Non-incapacitating FAILURE TO YIELD RIGHT OF WAY GATES & JACOBS 39.165655 -86.575956
4 2015 1 7 Weekend 1100.0 2-Car No injury/unknown FAILURE TO YIELD RIGHT OF WAY W 3RD 39.164848 -86.579625

Procedmos con la limpieza da la data

Realizamos una revisión de duplicados

Código
df.duplicated().value_counts()
False    53879
True        64
Name: count, dtype: int64

al parecer tenemos \(64\) filas repetidas

ahora observemos la información de los datos

Código
df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 53943 entries, 0 to 53942
Data columns (total 11 columns):
 #   Column             Non-Null Count  Dtype  
---  ------             --------------  -----  
 0   Year               53943 non-null  int64  
 1   Month              53943 non-null  int64  
 2   Day                53943 non-null  int64  
 3   Weekend?           53875 non-null  object 
 4   Hour               53718 non-null  float64
 5   Collision Type     53937 non-null  object 
 6   Injury Type        53943 non-null  object 
 7   Primary Factor     52822 non-null  object 
 8   Reported_Location  53908 non-null  object 
 9   Latitude           53913 non-null  float64
 10  Longitude          53913 non-null  float64
dtypes: float64(3), int64(3), object(5)
memory usage: 4.5+ MB

Veamos el rango de años que contiene la data

Código
print("Data desde el año",df.Year.min(), " hasta ", df.Year.max() )
Data desde el año 2003  hasta  2015

Analicemos los tipos de colisión que existen en la data

Código
df['Collision Type'].value_counts()
Collision Type
2-Car               37606
1-Car               10245
3+ Cars              3152
Moped/Motorcycle     1007
Bus                   850
Pedestrian            609
Cyclist               468
Name: count, dtype: int64

Visualización de la data

Frecuencia de los tipos de acciedentes

Código
sb.countplot(x=df['Collision Type'],palette='Set3')
plt.ylabel('Frecuencia')
plt.xticks(rotation=65)
plt.title("Frecuencia de tipos de Accidentes")
plt.show()
plt.clf()

<Figure size 672x480 with 0 Axes>

Observamos que existe una mayor cantidad de accidentes entre dos vehículos, por otro lado la cantidad de accidentes de bicicletas es la menor.

Accidentes ocurridos entre semana vs fin de semana

Código
sb.countplot(x=df['Weekend?'],palette='Accent')
plt.ylabel('Frecuencia')
plt.xticks(rotation=65)
plt.title("Entre semana vs Fin de semana")
plt.show()
plt.clf()

<Figure size 672x480 with 0 Axes>

Observamos que el Fin de semana es cuando mas ocurren accidentes.

Porcentaje de lesiones por Categoria

Código
les_val=df['Injury Type'].value_counts()
les_val
Injury Type
No injury/unknown     41603
Non-incapacitating    11136
Incapacitating         1089
Fatal                   115
Name: count, dtype: int64
Código
plt.pie(les_val,labels=les_val.index,startangle=30,shadow=True,autopct='%1.1f%%',rotatelabels=30,explode=(0.1,0.1,0.1,0.1),colors=[c4(0.9),c4(0.2),c4(0.3),c4(0.6)])
plt.title('Porcentaje de lesiones por Categoria')
plt.show()
plt.clf()

<Figure size 672x480 with 0 Axes>

Observamos que el \(0.2\%\) de accidentes son Fatales. Por otro lado algo que sería de mucho interes saber de cuantos accidentes no se conoce la lesión ocasionada puesto que la probabilidad de no tener lesiones es muy baja.

Motivo mas comun por el cual suceden accidentes

Primero indagaremos cuantos Factores Primarios existen en la data

Código
df['Primary Factor'].nunique()
55

Dado que existen \(55\) Factores Primarios nos quedaremos con el top 20

Código
pfdf=df['Primary Factor'].value_counts().head(20)
Código
fig=plt.figure(figsize=(10,10))
axis=fig.add_axes([1,1,1,1])
sb.swarmplot(x=pfdf,y=pfdf.index,ax=axis)
for i,j in enumerate(pfdf):
  axis.text(j,i,j)
plt.xlabel('Ocurrencia')
plt.title('Motivos principales por los que ocurren accidentes')
plt.show()
plt.clf()

<Figure size 672x480 with 0 Axes>

Top 30 lugares mas frecuente donde ocurren accidentes

Código
ldf=df['Reported_Location'].value_counts().head(30)
Código
fig1=plt.figure()
axis1=fig1.add_axes([1,1,1,1])
sb.barplot(x=ldf,y=ldf.index,ax=axis1,palette="viridis")
for i,j in enumerate(ldf):
  axis1.text(j,i,j,va='top')
axis1.set_xlabel('Frecuencia')
axis1.set_title('Lugares con mayor frecuencia de Accidentes')
plt.show()
plt.clf()

<Figure size 672x480 with 0 Axes>

Tipos de Colisiones en diferentes años

Código
años=df.groupby('Year')
keys=años.groups.keys()
Código
infobox=[]
for i in range(2003,2016):
  infobox.append(años.get_group(i)['Collision Type'].value_counts())
Código
c2=cm.get_cmap('terrain')
Código
from IPython.display import display, Markdown

Colisiones por Año

<Figure size 672x480 with 0 Axes>

Gráfico Dinamico

Código
import plotly.express as px
Código
px.histogram(df,x='Collision Type', 
animation_frame=df['Year'].sort_values(ascending=True),
color='Collision Type', title='Accidentes por Tipo de Colisión'
)